package com.lc.resolver;

import com.lc.annotation.Param;
import com.lc.annotation.SQL;
import com.lc.entity.SqlEntity;
import com.lc.entity.SqlParam;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ParamResolver {

    private Map<Method, SqlEntity> sqlEntityMap = new HashMap<>();

    public SqlEntity resolveSqlParam(Method method) {
        SqlEntity sqlEntity = sqlEntityMap.get(method);
        if (sqlEntity == null) {
            sqlEntity = obtainSqlEntity(method);
            sqlEntityMap.put(method, sqlEntity);
        }
        return sqlEntity;
    }

    private SqlEntity obtainSqlEntity(Method method) {
        SqlEntity sqlEntity;
        Pattern regex = Pattern.compile("\\$\\{([^}]*)\\}");
        sqlEntity = prepareCreateSqlEntity(method);
        Map<String, Class<?>> paramTypeMap = obtainParamMap(method);

        String sql = sqlEntity.getSql();
        Matcher matcher = regex.matcher(sql);
        List<SqlParam> sqlParams = new ArrayList<>();

        while (matcher.find()) {
            String paramName = matcher.group(1);
            SqlParam sqlParam = obtainSqlParam(paramTypeMap, paramName);
            sqlParams.add(sqlParam);
            if (sqlEntity.getSql().contains(paramName.trim())) {
                sql = sql.replace("${" + paramName.trim() + "}", "?");
            }
        }
        sqlEntity.setSql(sql);
        sqlEntity.setSqlParams(sqlParams);
        return sqlEntity;
    }

    private SqlParam obtainSqlParam(Map<String, Class<?>> paramTypeMap, String paramName) {
        SqlParam sqlParam = new SqlParam();
        sqlParam.setName(paramName);
        Class<?> paramType = paramTypeMap.get(paramName);
        sqlParam.setParamType(paramType);
        return sqlParam;
    }

    private SqlEntity prepareCreateSqlEntity(Method method) {
        SqlEntity entity = null;
        SQL sqlAnnotation = method.getAnnotation(SQL.class);
        if (sqlAnnotation != null) {
            entity = new SqlEntity();
            entity.setSql(sqlAnnotation.sql());
            entity.setReturnType(sqlAnnotation.returnType());
        }
        return entity;
    }

    public Map<String, Class<?>> obtainParamMap(Method method) {
        Map<String, Class<?>> paramTypeMap = new HashMap<>();
        Parameter[] parameters = method.getParameters();

        for (Parameter parameter : parameters) {
            Param paramAnnotation = parameter.getAnnotation(Param.class);
            String paramName = paramAnnotation.value();
            Class<?> paramType = parameter.getType();
            paramTypeMap.put(paramName, paramType);
        }

        return paramTypeMap;
    }

    public static void main(String[] args) {
        /*String sql = "select * from user where id= ${id} and name= ${name}";
        //正则表达式匹配
        Pattern regex = Pattern.compile("\\$\\{([^}]*)\\}");
        Matcher matcher = regex.matcher(sql);
        while (matcher.find()) {
            System.out.println(matcher.group(1));
        }*/
        String sql = "select * from user where id= ${id} and name= ${name}";
        ParamResolver paramResolver = new ParamResolver();
        //paramResolver.resolveSqlParam(sql);
    }


}
